package com.atguigu.tingshu.cdc.handler.impl;


import com.atguigu.tingshu.cdc.entity.CDCEntity;
import com.atguigu.tingshu.cdc.handler.EntryHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import top.javatool.canal.client.annotation.CanalTable;

@Component
@Slf4j
@CanalTable("album_info") //监听变更表
public class CdcEntryHandler implements EntryHandler<CDCEntity> {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;


    /**
     * 当album_info表有数据新增 此时会回掉到insert方法  并且回调的时候将canal获取到的数据给客户端
     *
     * @param cdcEntity
     */
    @Override
    public Boolean insert(CDCEntity cdcEntity) {
        System.out.println("插入的新数据：" + cdcEntity);
        try {
            // CDCEntity 中有一个 getId() 方法获取 ID
            String key = "cache:albumId:" + cdcEntity.getId();
            // cdcEntity 存储到 Redis 中
            redisTemplate.opsForValue().set(key, String.valueOf(cdcEntity));
            log.info("成功插入新数据到 Redis, ID: {}", cdcEntity.getId());
            return true;
        } catch (Exception e) {
            log.error("插入新数据到 Redis 时发生错误, ID: {}", cdcEntity.getId(), e);
            return false;
        }
    }

    /**
     * 当album_info表有数据修改(修改) 此时会回掉到update方法  并且回调的时候将canal获取到的新老数据给客户端
     *
     * @param before：修改之前的数据
     * @param after：修改之后的数据
     */
    @Override
    public Boolean update(CDCEntity before, CDCEntity after) {
        try {
            // 读线程读数据库+同步缓存时间
            log.info("监听到数据修改,ID:{}", after.getId());
            String key = "cache:albumId:" + after.getId();
            redisTemplate.delete(key);
            try {
                Thread.sleep(500);   // 压测得到读线程读数据库+同步缓存时间（300）
            } catch (InterruptedException e) {
                log.error("线程睡眠时发生中断", e);
                return false;
            }

            // 构建缓存键
            String cacheKey = "cache:info:" + after.getId();

            // 删除缓存
            Boolean isDeleted = redisTemplate.delete(cacheKey);
            if (Boolean.TRUE.equals(isDeleted)) {
                log.info("成功删除缓存, key: {}", cacheKey);
                return true;
            } else {
                log.warn("删除缓存失败, key: {}", cacheKey);
                // 发送缓存键到 RabbitMQ 进行重试
                sendToRabbitMQ(cacheKey);
                return false;
            }
        } catch (Exception e) {
            log.error("更新数据时发生错误", e);
            // 发送缓存键到 RabbitMQ 进行重试
            sendToRabbitMQ("cache:info:" + after.getId());
            return false;
        }
    }

    /**
     * 发送缓存键到 RabbitMQ 进行重试
     *
     * @param cacheKey 缓存键
     */
    private void sendToRabbitMQ(String cacheKey) {
        try {
            // 假设有一个 RabbitTemplate 用于发送消息到 RabbitMQ
            rabbitTemplate.convertAndSend("retryQueue", cacheKey);
            log.info("缓存键已发送到 RabbitMQ 进行重试, key: {}", cacheKey);
        } catch (Exception e) {
            log.error("发送缓存键到 RabbitMQ 时发生错误, key: {}", cacheKey, e);
        }
    }


    @Override
    public Boolean delete(CDCEntity cdcEntity) {

        System.out.println("删除之前的数据：" + cdcEntity);
        return null;
    }


}
